﻿using UnityEngine;
using System;
using System.IO;
using System.Text;
using System.Security.Cryptography;
using System.Reflection;

#if UNITY_EDITOR
using UnityEditor;
#endif

namespace XLua
{
    [LuaCallCSharp]
    public class LuaUtil
    {

        public static int Int(object o)
        {
            return Convert.ToInt32(o);
        }

        public static float Float(object o)
        {
            return (float)Math.Round(Convert.ToSingle(o), 2);
        }

        public static long Long(object o)
        {
            return Convert.ToInt64(o);
        }

        public static int RandomInt(int min, int max)
        {
            return UnityEngine.Random.Range(min, max);
        }

        public static float Random(float min, float max)
        {
            return UnityEngine.Random.Range(min, max);
        }

        public static string Uid(string uid)
        {
            int position = uid.LastIndexOf('_');
            return uid.Remove(0, position + 1);
        }

        public static long GetTime()
        {
            TimeSpan ts = new TimeSpan(DateTime.UtcNow.Ticks - new DateTime(1970, 1, 1, 0, 0, 0).Ticks);
            return (long)ts.TotalMilliseconds;
        }

        /// <summary>
        /// 计算字符串的MD5值
        /// </summary>
        public static string md5(string source)
        {
            MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
            byte[] data = System.Text.Encoding.UTF8.GetBytes(source);
            byte[] md5Data = md5.ComputeHash(data, 0, data.Length);
            md5.Clear();

            string destString = "";
            for (int i = 0; i < md5Data.Length; i++)
            {
                destString += System.Convert.ToString(md5Data[i], 16).PadLeft(2, '0');
            }
            destString = destString.PadLeft(32, '0');
            return destString;
        }

        /// <summary>
        /// 计算文件的MD5值
        /// </summary>
        public static string md5file(string file)
        {
            try
            {
                FileStream fs = new FileStream(file, FileMode.Open);
                System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
                byte[] retVal = md5.ComputeHash(fs);
                fs.Close();

                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < retVal.Length; i++)
                {
                    sb.Append(retVal[i].ToString("x2"));
                }
                return sb.ToString();
            }
            catch (Exception ex)
            {
                throw new Exception("md5file() fail, error:" + ex.Message);
            }
        }

        public static bool HaveDirectory(string dir){
            return Directory.Exists(dir);
        }
        public static void DeleteDirectory(string dir,bool recursive){
            Directory.Delete(dir,recursive);
        }
        public static void DeleteFile(string path){
            File.Delete(path);
        }


        /// <summary>
        /// 清理内存
        /// </summary>
        public static void ClearMemory()
        {
            GC.Collect(); Resources.UnloadUnusedAssets();
            if (!XLua.LuaManager.IsInited) return;
            LuaManager mgr = LuaManager.Instance;
            if (mgr != null && mgr.Lua != null) mgr.Lua.GC();
        }

        /// <summary>
        /// 取得数据存放目录
        /// </summary>
        public static string DataPath
        {
            get
            {
                if (Application.isMobilePlatform)
                {
                    return Application.persistentDataPath + "/";
                }
                return Application.streamingAssetsPath + "/";
            }
        }

        public static string GetRelativePath()
        {
            if (Application.isEditor)
                return "file://" + System.Environment.CurrentDirectory.Replace("\\", "/") + "/Assets/" + Application.streamingAssetsPath + "/";
            else if (Application.isMobilePlatform || Application.isConsolePlatform)
                return "file:///" + DataPath;
            else // For standalone player.
                return "file://" + Application.streamingAssetsPath + "/";
        }

        /// <summary>
        /// 取得行文本
        /// </summary>
        public static string GetFileText(string path)
        {
            return File.ReadAllText(path);
        }

        /// <summary>
        /// RenderTexture 转Texture
        /// </summary>
        /// <returns>The texture to texture2 d.</returns>
        /// <param name="rt">Rt.</param>
        public static Texture2D RenderTextureToTexture2D(RenderTexture rt, Rect rect)
        {
            if (rt != null)
            {
                Texture2D t = new Texture2D((int)rect.width, (int)rect.height, TextureFormat.ARGB32, false);
                RenderTexture.active = rt;
                t.ReadPixels(rect, 0, 0, false);
                t.Apply();
                RenderTexture.active = null;
                return t;
            }
            return null;
        }

        /// <summary>
        /// 写二进制
        /// </summary>
        /// <param name="path">Path.</param>
        /// <param name="bytes">Bytes.</param>
        public static void WriteBytes(string path, byte[] bytes)
        {
            string dir = Path.GetDirectoryName(path);
            if (!Directory.Exists(dir))
            {
                Directory.CreateDirectory(dir);
            }
            File.WriteAllBytes(path, bytes);
        }

        /// <summary>
        /// 保存RenderTexture为png 到本地
        /// </summary>
        /// <param name="filePath">File path.</param>
        /// <param name="rt">Rt.</param>
        public static void SaveRenderTexture(string filePath, RenderTexture rt)
        {
            if (rt)
            {
                Texture2D t = RenderTextureToTexture2D(rt, new Rect(0, 0, rt.width, rt.height));
                byte[] bytes = t.EncodeToPNG();
                WriteBytes(filePath, bytes);
            }
        }
        /// <summary>
        /// 保存Texture2D为png 到本地
        /// </summary>
        /// <param name="filePath">File path.</param>
        /// <param name="t">T.</param>
        public static void SaveTexture2D(string filePath, Texture2D t)
        {
            if (t)
            {
                byte[] bytes = t.EncodeToPNG();
                WriteBytes(filePath, bytes);
            }
        }

        /// <summary>
        /// 是否是Mobile平台
        /// </summary>
        /// <returns><c>true</c> if this instance is mobile; otherwise, <c>false</c>.</returns>
        public bool IsMobile()
        {
            return Application.isMobilePlatform;
        }
        /// <summary>
        /// 是否是Android 平台
        /// </summary>
        /// <returns><c>true</c> if this instance is android; otherwise, <c>false</c>.</returns>
        public bool IsAndroid()
        {
            return Application.platform == RuntimePlatform.Android;
        }
        /// <summary>
        /// 是否是ios 平台
        /// </summary>
        /// <returns><c>true</c> if this instance is IO; otherwise, <c>false</c>.</returns>
        public bool IsIOS()
        {
            return Application.platform == RuntimePlatform.IPhonePlayer;
        }
        /// <summary>
        /// 是否是Editor
        /// </summary>
        /// <returns><c>true</c> if this instance is editor; otherwise, <c>false</c>.</returns>
        public bool IsEditor()
        {
            return Application.isEditor;
        }

        /// <summary>
        /// 应用程序内容路径
        /// </summary>
        public static string AppContentPath()
        {
            string path = string.Empty;
            switch (Application.platform)
            {
                case RuntimePlatform.Android:
                    path = "jar:file://" + Application.dataPath + "!/assets/";
                    break;
                case RuntimePlatform.IPhonePlayer:
                    path = Application.dataPath + "/Raw/";
                    break;
                default:
                    path = Application.dataPath + "/";
                    break;
            }
            return path;
        }

        public static void Log(string str)
        {
            Debug.Log(str);
        }

        public static void LogWarning(string str)
        {
            Debug.LogWarning(str);
        }

        public static void LogError(string str)
        {
            Debug.LogError(str);
        }

        public static void ClearAllEvents(object objectHasEvents)
        {
            var events = objectHasEvents.GetType().GetEvents();
            if (events == null || events.Length < 1)
            {
                return;
            }
            foreach (var info in events)
            {
                ClearEvents(objectHasEvents, info.Name);
            }
        }

        public static void ClearEvents(object objectHasEvents, string eventName)
        {
            if (objectHasEvents == null)
            {
                return;
            }
            Delegate[] invokeList = GetObjectEventList(objectHasEvents, eventName);
            if (invokeList != null)
            {
                Type t = objectHasEvents.GetType();
                foreach (Delegate del in invokeList)
                {
                    t.GetEvent(eventName).RemoveEventHandler(objectHasEvents, del);
                }
            }
        }

        private static Delegate[] GetObjectEventList(object p_Object, string p_EventName)
        {
            FieldInfo _Field = p_Object.GetType().GetField(p_EventName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public | BindingFlags.Static);
            if (_Field == null)
            {
                return null;
            }
            object _FieldValue = _Field.GetValue(p_Object);
            if (_FieldValue != null && _FieldValue is Delegate)
            {
                Delegate _ObjectDelegate = (Delegate)_FieldValue;
                return _ObjectDelegate.GetInvocationList();
            }

            return null;
        }


        /// <summary>
        /// 通过文件文件加载图片
        /// </summary>
        /// <returns>The texture2 d.</returns>
        /// <param name="relativePath">Relative path.</param>
        /// <param name="readOnly">If set to <c>true</c> read only.</param>
        public static Texture2D LoadTexture2D(string path, bool readOnly = true, TextureFormat format = TextureFormat.ARGB32)
        {
            if (System.IO.File.Exists(path))
            {
                var data = System.IO.File.ReadAllBytes(path);
                Texture2D t = new Texture2D(2, 2, format, false, true);
                t.LoadImage(data, readOnly);
                return t;
            }
            return null;
        }

        public static Texture2D LoadImageData(byte[] data, bool readOnly = true, TextureFormat format = TextureFormat.ARGB32)
        {
            if (data != null)
            {
                Texture2D t = new Texture2D(2, 2, format, false, true);
                t.LoadImage(data, readOnly);
                return t;
            }
            return null;
        }
    }
}